package com.Blog.test_2_1_spring_blog;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Test21SpringBlogApplication {

    public static void main(String[] args) {
        SpringApplication.run(Test21SpringBlogApplication.class, args);

        // 创建一个项目的时候
        // 先把基本的框架搭建好
        // 然后再考虑内容
        // 框架搭建好之后
        // 首先把 model 层的实体类建造好
        // 然后 创建 mapper 层 数据
        //   这一层要先考虑需要什么
        //      1. 用户登录, 校验用户名和密码是否正确 (根据用户名查询用户信息, 比对密码是否正确, 不太建议密码跟用户名一块查询)
        //         这时候就有一个sql了, 根据用户名查询用户信息
        //      2. 进入之后 博客列表页有哪些信息
        //          sql : 根据用户 id 查询用户信息
        //          sql : 获取博客列表
        //      3 之后博客详情页所设计到的
        //          sql: 根据博客id 获取博客详情
        //          sql: 根据博客id编辑博客
        //          sql: 根据博客id删除博客
        //      4. 博客的添加和修改
        //           sql: 根据输入的内容去添加博客.
        //  这就是整个项目中所设计到的操作


        // 接下来进入功能开发
        // 开发博客列表
        // 约定前后端交互接口
        // [请求]
        ///blog/getlist
        //[响应]
        //{
        // "code": 200,
        // "msg": "",
        // "data": [{
        // "id": 1,
        // "title": "第⼀篇博客",
        // "content": "111我是博客正⽂我是博客正⽂我是博客正⽂",
        // "userId": 1,
        // "deleteFlag": 0,
        // "createTime": "2023-10-21 16:56:57",
        // "updateTime": "2023-10-21T08:56:57.000+00:00"
        // },
        // .....
        // ]
        //}

        // 实现博客详情
        // [请求]
        ///blog/getBlogDetail?blogId=1
        //[响应]
        //{
        // "code": 200,
        // "msg": "",
        // "data": {
        // "id": 1,
        // "title": "第⼀篇博客",
        // "content": "111我是博客正⽂我是博客正⽂我是博客正⽂",
        // "userId": 1,


        // 实现登录
        // 先分析 登录
        // 传统思路: 1. 先校验, 输入账号密码, 后端校验
        //          2. 后端校验成功 存在 Session 中, 返回 Cookie
        //          3. 前端进行页面跳转, 后端访问时,携带Cookie,SessionId, 后端从 session 中取值, 检验用户是否登录

        // 这种方式会存在问题, session 是存储在 服务器的内存中的 服务器重启 session 就丢失了,
        // 用户刚登陆完, 就遇到了服务器重启, 用户就会需要重新登录,
        // 还有一个问题现在的服务大多都不是单机部署了, 至少是双机的,
        // 容易发⽣单点故障. (单点故障: ⼀旦这台服务器挂
        //了, 整个应⽤都没法访问了). 所以通常情况下, ⼀个Web应⽤会部署在多个服务器上, 通过Nginx等进⾏负载均衡.
        // 此时, 来⾃⼀个⽤⼾的请求就会被分发到不同的服务器上.
        // ,集群环境下⽆法直接使⽤Session.

        // 1. ⽤⼾登录 ⽤⼾登录请求, 经过负载均衡, 把请求转给了第⼀台服务器, 第⼀台服务器进⾏账号密码
        //验证, 验证成功后, 把Session存在了第⼀台服务器上
        //2. 查询操作 ⽤⼾登录成功之后, 携带Cookie(⾥⾯有SessionId)继续执⾏查询操作, ⽐如查询博客列
        //表. 此时请求转发到了第⼆台机器, 第⼆台机器会先进⾏权限验证操作(通过SessionId验证⽤⼾是否
        //登录), 此时第⼆台机器上没有该⽤⼾的Session, 就会出现问题, 提⽰⽤⼾登录, 这是⽤⼾不能忍受的.

        // 此时的解决方案有两中
        // 1. Session 存储在一个公用的机器上(或者缓存等),
        // 2. 最常见的就是: token

        // 那么什么是 token 呢?
        // token 就是一个字符串, 只不过这个字符串带有一定信息, 和 Cookie 类似的
        // token 就相当于一个 身份证, 是自己主管的
        // token 是客户端进行访问时携带的, 但是这个身份标识是不能伪造的

        // 接下来使用 token 来解决上述问题

        // token 的实现方式有很多
        // 最常用的就是 **** 令牌技术 ****
        // 令牌其实就是⼀个⽤⼾⾝份的标识, 名称起的很⾼⼤上, 其实本质就是⼀个字符串
        // 服务器有验证token真假的功能
        // token最主要的不是加密, 而是不能伪造的功能

        // token 所具备的两个信息: 一个是带有一定信息的字符串, 一个是不能伪造

        // 令牌的优缺点
        //优点:
        //• 解决了集群环境下的认证问题
        //• 减轻服务器的存储压⼒(⽆需在服务器端存储)
        //缺点:
        //需要⾃⼰实现(包括令牌的⽣成, 令牌的传递, 令牌的校验)

        // 令牌本质就是⼀个字符串, 他的实现⽅式有很多, 我们采⽤⼀个 ***JWT令牌*** 来实现

        // 集群和分布式的区别
        // 分布式就是 大家共同完成某一个任务
        // 集群就是 聚集到一起,各自实现各自的

        // JWT组成
        //JWT由三部分组成, 每部分中间使⽤点 (.) 分隔，⽐如：aaaaa.bbbbb.cccc
        //• Header(头部) 头部包括令牌的类型（即JWT）及使⽤的哈希算法（如HMAC SHA256或RSA）
        //• Payload(负载) 负载部分是存放有效信息的地⽅, ⾥⾯是⼀些⾃定义内容. ⽐如:
        //{"userId":"123","userName":"zhangsan"} , 也可以存在jwt提供的现场字段, ⽐如
        //exp(过期时间戳)等.
        //此部分不建议存放敏感信息, 因为此部分可以解码还原原始内容.
        //• Signature(签名) 此部分⽤于防⽌jwt内容被篡改, 确保安全性.
        //防⽌被篡改, ⽽不是防⽌被解析.
        //JWT之所以安全, 就是因为最后的签名. jwt当中任何⼀个字符被篡改, 整个令牌都会校验失败.
        //就好⽐我们的⾝份证, 之所以能标识⼀个⼈的⾝份, 是因为他不能被篡改, ⽽不是因为内容加密.(任
        //何⼈都可以看到⾝份证的信息, jwt 也是)

        // 对上⾯部分的信息, 使⽤Base64Url 进⾏编码, 合并在⼀起就是jwt令牌
        // Base64是编码⽅式，⽽不是加密⽅式


        // 操作步骤:
        // 1.JWT令牌技术需要引入依赖
        // 2.

        // 接下来在登录流程中如何使用令牌
        // 使用 token 的方式 步骤:
        // 根据用户名和密码验证密码是否正确
        // 如果密码正确, 后端生成 token 并返回给前端 (可以放在 cookie 中 也可以放在本地的存储中)
        // 后续访问时 携带token 后端进行校验 token 的合法性

        // 那么token 应该放在哪里? 通常放在 http请求的 header中, 而不是作为请求来的

        // 接下来进行强制登录

        // 然后实现 显示用户的信息
        // 显示用户信息 博客列表显示当前登录的信息
        // 博客详情页, 获取当前文章作者的信息

        // 实现用户退出

        // 发布博客
        // 定义接口
        // [请求]
        ///blog/add
        //title=标题&content=正⽂...
        //[响应]
        //{
        // "code": 200,
        // "msg": "",
        // "data": true

        // 接下来实现编辑和删除博客
        // 只有作者本人才可以实现编辑和删除
        // 登录用户和作者是同一个人才可以实现编辑/删除
        // 在博客详情页去判断是否显示 编辑/删除 按钮
        // 判断条件 就是: 当前登录用户 是否 等于 作者, 是 就显示 不是 就不显示
        // 有两种思路:
        //    1. 单独写一个接口, 返回 true 或者 false (登录 == 作者)
        //    2. 获取博客详情时, 同时返回登录用户是否为 作者
        // 第一种方案是推荐的 , 因为符合 单一原则
        // 但是这里实现的是第二种方案  原因是比较简单


        // 接下来进行编辑博客 和 删除博客
        // 编辑的请求接口 是 update
        //  删除的请求接口 是 delete



        // ******* 加密/加盐 *******
        // 加密介绍
        //在MySQL数据库中, 我们常常需要对密码, ⾝份证号, ⼿机号等敏感信息进⾏加密, 以保证数据的安全性.
        //如果使⽤明⽂存储, 当⿊客⼊侵了数据库时, 就可以轻松获取到⽤⼾的相关信息, 从⽽对⽤⼾或者企业造
        //成信息泄漏或者财产损失.
        //⽬前我们⽤⼾的密码还是明⽂设置的, 为了保护⽤⼾的密码信息, 我们需要对密码进⾏加密

        // 密码算法分类
        //密码算法主要分为三类: 对称密码算法, ⾮对称密码算法, 摘要算法

        // 1. 对称密码算法 是指加密秘钥和解密秘钥相同的密码算法. 常⻅的对称密码算法有: AES, DES, 3DES,
        //RC4, RC5, RC6 等.
        //2. ⾮对称密码算法 是指加密秘钥和解密秘钥不同的密码算法. 该算法使⽤⼀个秘钥进⾏加密, ⽤另外⼀
        //个秘钥进⾏解密.
        //◦ 加密秘钥可以公开，⼜称为 公钥
        //◦ 解密秘钥必须保密，⼜称为 私钥
        //常⻅的⾮对称密码算法有: RSA, DSA, ECDSA, ECC 等
        // (1.2 都是可逆的, 就是能够恢复到原来的状态)
        //3. 摘要算法 是指把任意⻓度的输⼊消息数据转化为固定⻓度的输出数据的⼀种密码算法. 摘要算法是
        //不可逆的, 也就是⽆法解密. 通常⽤来检验数据的完整性的重要技术, 即对数据进⾏哈希计算然后⽐
        //较摘要值, 判断是否⼀致. 常⻅的摘要算法有: MD5, SHA系列(SHA1, SHA2等), CRC(CRC8, CRC16,
        //CRC32)
        // (3是不可逆的)

        // 主要学习 MD5
        // 是通过 明文加加盐组合成的
        //采⽤为⼀个密码拼接⼀个随机字符来进⾏加密, 这个随机字符我们称之为"盐". 假如有⼀个加
        //盐后的加密串，⿊客通过⼀定⼿段这个加密串, 他拿到的明⽂并不是我们加密前的字符串, ⽽是加密前
        //的字符串和盐组合的字符串, 这样相对来说⼜增加了字符串的安全性

        //MD5是不可逆的, 通常采⽤"判断哈希值是否⼀致"来判断密码是否正确.
        //如果⽤⼾输⼊的密码, 和盐值⼀起拼接后的字符串经过加密算法, 得到的密⽂相同, 我们就认为密码正确
        //(密⽂相同, 盐值相同, 推测明⽂相同)


    }

}
